package com.ruoyi.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.ParkingCardRefund;
import com.ruoyi.dto.WeChatRefundDto;
import com.ruoyi.mapper.ParkingCardRefundMapper;
import com.ruoyi.service.IWeChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.mapper.ParkingCardOrderMapper;
import com.ruoyi.domain.ParkingCardOrder;
import com.ruoyi.service.IParkingCardOrderService;
import org.springframework.transaction.annotation.Transactional;

import static com.ruoyi.common.utils.SecurityUtils.getUsername;

/**
 * 停车卡订单Service业务层处理
 * 
 * @author dongdong
 * @date 2025-09-09
 */
@Slf4j
@Service
public class ParkingCardOrderServiceImpl implements IParkingCardOrderService 
{
    @Autowired
    private ParkingCardOrderMapper parkingCardOrderMapper;
    @Autowired
    private ParkingCardRefundMapper parkingCardRefundMapper;
    @Autowired
    private IWeChatService weChatService;

    /**
     * 查询停车卡订单
     * 
     * @param id 停车卡订单主键
     * @return 停车卡订单
     */
    @Override
    public ParkingCardOrder selectParkingCardOrderById(Long id)
    {
        return parkingCardOrderMapper.selectParkingCardOrderById(id);
    }

    /**
     * 查询停车卡订单列表
     * 
     * @param parkingCardOrder 停车卡订单
     * @return 停车卡订单
     */
    @Override
    @DataScope(deptAlias = "pco")
    public List<ParkingCardOrder> selectParkingCardOrderList(ParkingCardOrder parkingCardOrder)
    {
        return parkingCardOrderMapper.selectParkingCardOrderList(parkingCardOrder);
    }

    /**
     * 新增停车卡订单
     * 
     * @param parkingCardOrder 停车卡订单
     * @return 结果
     */
    @Override
    public int insertParkingCardOrder(ParkingCardOrder parkingCardOrder)
    {
        parkingCardOrder.setCreateTime(DateUtils.getNowDate());
        return parkingCardOrderMapper.insertParkingCardOrder(parkingCardOrder);
    }

    /**
     * 修改停车卡订单
     * 
     * @param parkingCardOrder 停车卡订单
     * @return 结果
     */
    @Override
    public int updateParkingCardOrder(ParkingCardOrder parkingCardOrder)
    {
        parkingCardOrder.setUpdateTime(DateUtils.getNowDate());
        return parkingCardOrderMapper.updateParkingCardOrder(parkingCardOrder);
    }

    /**
     * 批量删除停车卡订单
     * 
     * @param ids 需要删除的停车卡订单主键
     * @return 结果
     */
    @Override
    public int deleteParkingCardOrderByIds(Long[] ids)
    {
        return parkingCardOrderMapper.deleteParkingCardOrderByIds(ids);
    }

    /**
     * 删除停车卡订单信息
     * 
     * @param id 停车卡订单主键
     * @return 结果
     */
    @Override
    public int deleteParkingCardOrderById(Long id)
    {
        return parkingCardOrderMapper.deleteParkingCardOrderById(id);
    }

    /**
     * 1.先通过订单id查询订单，判断退款金额是否大于订单金额
     * 2.通过订单金额查询退款订单记录
     * 3.判断退款总金额（本次申请金额 + 已退款金额）是否大于订单支付金额（部分退款的订单用到）
     */
    @Override
    @Transactional
    public int refund(WeChatRefundDto weChatRefundDto) {
        Long orderId = weChatRefundDto.getOrderId();
        ParkingCardOrder parkingCardOrder = parkingCardOrderMapper.selectParkingCardOrderById(orderId);
        Optional.ofNullable(parkingCardOrder).orElseThrow(() -> new RuntimeException("订单不存在"));
        String orderNo = parkingCardOrder.getOrderNo();
        BigDecimal payAmount = parkingCardOrder.getPayAmount();
        BigDecimal alreadyRefundAmount = BigDecimal.ZERO;
        // 查询退款记录
        List<ParkingCardRefund> refundList = parkingCardRefundMapper.selectParkingCardRefundByOrderNo(orderNo, 5);
        if(!refundList.isEmpty()){
            alreadyRefundAmount = new BigDecimal(refundList.stream().mapToDouble(e->e.getRefundAmount().doubleValue()).sum()).setScale(2, RoundingMode.HALF_UP);
        }
        // 可退款金额
        BigDecimal allowRefundAmount = payAmount.subtract(alreadyRefundAmount);
        if(allowRefundAmount.compareTo(BigDecimal.ZERO) < 0){
            throw new RuntimeException("订单已退款");
        }
        int refundType = weChatRefundDto.getRefundType().intValue();
        if(refundType == 1){ // 部分退款
            if (Objects.isNull(weChatRefundDto.getRefundAmount())){
                throw new RuntimeException("请填写退款金额");
            }
            if (weChatRefundDto.getRefundAmount().compareTo(payAmount) > 0) {
                throw new RuntimeException("退款金额不能大于支付金额");
            }
            if(weChatRefundDto.getRefundAmount().compareTo(allowRefundAmount) > 0){
                throw new RuntimeException("已退款"+alreadyRefundAmount+"元，还可申请退款"+payAmount.subtract(alreadyRefundAmount)+"元");
            }
        }
        if(refundType == 2){ // 全额退款
            weChatRefundDto.setRefundAmount(allowRefundAmount);
        }

        ParkingCardRefund parkingCardRefund = new ParkingCardRefund();
        String refundNo = StringUtils.getOrderNo("CRF");
        parkingCardRefund.setRefundNo(refundNo);
        parkingCardRefund.setOrderId(orderId);
        parkingCardRefund.setOrderNo(orderNo);
        parkingCardRefund.setOrderAmount(payAmount);
        parkingCardRefund.setRefundType(refundType);
        parkingCardRefund.setRefundAmount(weChatRefundDto.getRefundAmount());
        parkingCardRefund.setRefundReason("停车卡退款");
        Date date = new Date();
        parkingCardRefund.setApplyTime(date);
        parkingCardRefund.setApplyBy(getUsername());
        parkingCardRefund.setCreateTime(date);

        // 微信退款
        WeChatRefundDto weChatRefund = new WeChatRefundDto();
        weChatRefund.setOrderNo(parkingCardOrder.getOrderNo());
        weChatRefund.setTransNo(parkingCardOrder.getTransNo());
        weChatRefund.setRefundNo(refundNo);
        weChatRefund.setRefundAmount(weChatRefundDto.getRefundAmount());
        weChatRefund.setOrderAmount(payAmount);
        weChatRefund.setReason("停车卡退款");
        Map<String, Object> result = weChatService.weChatRefund(weChatRefund);
        log.info("停车卡退款申请结果：{}", result);
        parkingCardRefund.setRefundStatus(4);
        return parkingCardRefundMapper.insertParkingCardRefund(parkingCardRefund);
    }
}
